/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include <fstream>
#include "Module/src/common/JsonHelper.h"
#include "constant/PluginConstants.h"
#include "ShareResourceManager.h"

using namespace std;
namespace {
    constexpr auto MODULE = "ShareResourceManager";
    constexpr auto BACKUP_KEY_SUFFIX = "_backup_stats";
    constexpr auto SCAN_KEY_SUFFIX = "_scan_stats";
}
ShareResourceManager::ShareResourceManager()
{}

ShareResourceManager::~ShareResourceManager()
{}
void ShareResourceManager::SetResourcePath(const std::string &path, const std::string &jobId)
{
    lock_guard<std::mutex> lk(m_cachePathMutex);
    auto it = m_jobCachePathMap.begin();
    it = m_jobCachePathMap.find(jobId);
    if (it != m_jobCachePathMap.end()) {
        return;
    }
    m_jobCachePathMap.emplace(jobId, path);
}

std::string ShareResourceManager::CalculateKey(ShareResourceType resType, const std::string &jobId)
{
    if (resType == ShareResourceType::BACKUP) {
        return jobId + BACKUP_KEY_SUFFIX;
    } else if (resType == ShareResourceType::SCAN) {
        return jobId + SCAN_KEY_SUFFIX;
    }
    return "";
}
std::string ShareResourceManager::GetFileName(ShareResourceType resType, const std::string &jobId)
{
    string path = GetJobResourcePath(jobId);
    path.append("/");
    path.append(jobId);
    if (resType == ShareResourceType::BACKUP) {
        path.append(BACKUP_KEY_SUFFIX).append(".json");
    } else if (resType == ShareResourceType::SCAN) {
        path.append(SCAN_KEY_SUFFIX).append(".json");
    }
    return path;
}
void ShareResourceManager::Wait(ShareResourceType resType, const std::string &jobId)
{
    string semaphoreKey = CalculateKey(resType, jobId);
    shared_ptr<Semaphore> semaphorePtr = GetSemaphore(semaphoreKey);
    semaphorePtr->Wait();
}
void ShareResourceManager::Signal(ShareResourceType resType, const std::string &jobId)
{
    string semaphoreKey = CalculateKey(resType, jobId);
    shared_ptr<Semaphore> semaphorePtr = GetSemaphore(semaphoreKey);
    semaphorePtr->Signal();
}

bool ShareResourceManager::DeleteResource(ShareResourceType resType, const std::string &jobId)
{
    string fileName = GetFileName(resType, jobId);
    RemoveResourceCache(resType, jobId);
    bool result = PluginUtils::Remove(fileName);
    if (!result) {
        HCP_Log(ERR, MODULE) << "DeleteResource, delete file failed, path:"<< fileName << HCPENDLOG;
    }
    return result;
}

void ShareResourceManager::RemoveResourceCache(ShareResourceType resType, const std::string &jobId)
{
    string key = CalculateKey(resType, jobId);
    RemoveSemaphore(key);
    RemoveJobResourcePath(jobId);
}

bool ShareResourceManager::CanReportStatToPM(const std::string mainTaskId)
{
    DBGLOG("Enter CanReportStatToPM");
    lock_guard<std::mutex> lk(m_taskMutex);
    time_t lastUpdateTime = 0;
    if (m_TaskReportMap.count(mainTaskId)) {
        lastUpdateTime = m_TaskReportMap[mainTaskId];
    } else {
        m_TaskReportMap[mainTaskId] = PluginUtils::GetCurrentTimeInSeconds();
        return false;
    }
    if ((PluginUtils::GetCurrentTimeInSeconds() - lastUpdateTime) < BACKUP_REPORT_CIRCLE_TIME_IN_SEC) {
        DBGLOG("Exit CanReportStatToPM ret false");
        return false;
    }
    DBGLOG("CanReportStatToPM, lastTime: %d, currTime: %d, Report Interval: %d", lastUpdateTime,
        PluginUtils::GetCurrentTimeInSeconds(), PluginUtils::GetCurrentTimeInSeconds() - lastUpdateTime);
    m_TaskReportMap[mainTaskId] = PluginUtils::GetCurrentTimeInSeconds();
    DBGLOG("Exit CanReportStatToPM ret true");
    return true;
}

std::shared_ptr<Semaphore> ShareResourceManager::GetSemaphore(const std::string& key)
{
    lock_guard<std::mutex> lk(m_mutex);
    auto it = m_ResSemaphoreMap.begin();
    it = m_ResSemaphoreMap.find(key);
    if (it != m_ResSemaphoreMap.end()) {
        return it->second;
    }
    shared_ptr<Semaphore> semaphorePtr = make_shared<Semaphore>(1);
    m_ResSemaphoreMap.emplace(key, semaphorePtr);
    return semaphorePtr;
}
void ShareResourceManager::RemoveSemaphore(const std::string& key)
{
    lock_guard<std::mutex> lk(m_mutex);
    auto it = m_ResSemaphoreMap.begin();
    it = m_ResSemaphoreMap.find(key);
    if (it != m_ResSemaphoreMap.end()) {
        m_ResSemaphoreMap.erase(it);
    }
}

void ShareResourceManager::RemoveJobResourcePath(const std::string& jobId)
{
    lock_guard<std::mutex> lk(m_cachePathMutex);
    auto it = m_jobCachePathMap.begin();
    it = m_jobCachePathMap.find(jobId);
    if (it != m_jobCachePathMap.end()) {
        m_jobCachePathMap.erase(it);
    }
}

std::string ShareResourceManager::GetJobResourcePath(const std::string &jobId)
{
    lock_guard<std::mutex> lk(m_cachePathMutex);
    auto it = m_jobCachePathMap.begin();
    it = m_jobCachePathMap.find(jobId);
    if (it != m_jobCachePathMap.end()) {
        return it->second;
    }
    WARNLOG("job resource path is empty,jobId:%s", jobId.c_str());
    return "";
}
ShareResourceManager& ShareResourceManager::GetInstance()
{
    static ShareResourceManager instance;
    return instance;
}